home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 145
/
Gekkan Dennou Club - 2000.6 Vol. 145 (Japan).7z
/
Gekkan Dennou Club - 2000.6 Vol. 145 (Japan) (Track 1).bin
/
docs
/
asm
/
asmtime.doc
next >
Wrap
Text File
|
2000-05-08
|
7KB
|
274 lines
━───────────────────────────────────
X680x0アセンブラ講座 ~番外編~
《命令のクロック数を計るプログラム》
鎌田 誠
────────────────────────────────────
Motorola のマニュアルに書いてある命令のクロック数を検証するには、自分
でプログラムを書いて実際に所要時間を調べるのが一番確実です。その具体例を
紹介します。
━───────────────────────────────────
_optime
────────────────────────────────────
● _optime とは
サブルーチン _optime は、指定されたサブルーチンを呼び出して帰ってくる
までの時間を計るプログラムです。タイマーを 2 本使って 1μs(0.000001 秒)
単位で最大 12799μs(0.012799 秒)まで計ることができます。これを越えると
正しい結果が得られません。
10MHz の 1 クロックは 0.1μs なので、命令 1 個の時間を直接計ることはで
きません。12799μs 以内でなるべく多く繰り返して、全体の所要時間を繰り返
した回数で割ることで 1 回あたりの所要時間を求めます。なお、結果には命令
を繰り返すために使用される分岐命令の所要時間も含まれます。また、呼び出し
に必要な jsr/rts の所要時間も含まれるので、なるべく多く繰り返した方が正
確な値が求まります。
● _optime の呼び出し方
_optime は Timer-C と Timer-D を使います。これらのタイマーを標準以外の
目的で使用している場合は正常に動作しません。
_optime は必ずスーパーバイザモードで呼び出さなければなりません。
_optime の呼び出し方は次のようになっています。
┌────────────────────────────────
│ move.l #count,-(sp) ;初期化ルーチンのパラメータ(ループ回数など)
│ pea.l op_tini ;後始末ルーチン(不要ならば0)
│ pea.l op_init ;初期化ルーチン(不要ならば0)
│ pea.l op_main ;計測するルーチン
│ jsr optime
│ lea.l (16,sp),sp
次のような前宣言をすることで C のプログラムから呼び出すこともできます。
┌────────────────────────────────
│int optime(void op_main(void), void op_init(int count), void op_tini(void), int count);
● _optime の動作
_optime は、op_init(初期化ルーチン)、op_main(計測するルーチン)、
op_tini(後始末ルーチン)の順序で 2 回呼び出し、2 回目の op_main の所要
時間だけ計測します。2 回呼び出すのは、計測ルーチンをキャッシュに乗せるた
めです。一連の呼び出し(6 回のサブルーチンコール)は割り込みを禁止した状
態で行われます。
●レジスタの扱いについて
op_init では op_main で使用するレジスタの準備をして下さい。optime の 4
番目の引数(count)が op_init に渡されるので、これをレジスタに設定するな
どします。メモリを確保するといった大掛かりな処理も可能ですが、割り込みが
禁止されているのでディスクのアクセスなどはできません。op_init で設定され
たレジスタは d0-d7/a0-a5 の内容がそのまま op_main に渡されます。
op_main では d0-d7/a0-a6 をすべて使えます。ただし、_optime が op_main
を呼び出すときに jsr (a6) として a6 レジスタを使用しているので、a6 レジ
スタは op_init から引き継ぐことができません。
op_tini は後始末です。通常は不要でしょう。op_init でメモリを確保したと
きは必ずここで開放して下さい。
◎ optime.s を見る TYPE=DOC:optime.s
━───────────────────────────────────
メインルーチン
────────────────────────────────────
_optime はサブルーチンなので、これを実行するにはメインルーチンが必要で
す。
計測対象のルーチンを _op_init、_op_main、_op_tini という名前で呼び出す
メインルーチンを用意しました。コマンドラインでループ回数(op_init の引数)
を指定することができます。このソースだけ C で書いてあります。
◎ main.c を見る TYPE=DOC:main.c
━───────────────────────────────────
具体例(その1)
────────────────────────────────────
NOP+SUBQ.L #xx,Dn+Bcc.S の所要クロック数を調べます。
NOP は 68000 では 4 クロック、68030 では 2 クロック、68060 では 9 クロ
ックの命令です。
SUBQ.L #xx,Dn は 68000 では 8 クロック、68030 では 2 クロック、68060
では 1 クロックの命令です。
Bcc.S は 68000 では 10 クロック、68030 では 6 クロック、68060 では 0
クロック(分岐予測あり)です。
●ソース
┌────────────────────────────────
1│;nop+subq.l+bcc.s
2│ .text
3│ .even
4│_op_init::
5│ move.l (4,sp),d0
6│ rts
7│
8│ .even
9│_op_tini::
10│ rts
11│
12│ .align 16
13│_op_main::
14│ ; 000 030 060
15│@@: nop ; 4 0-2-0 9
16│ subq.l #1,d0 ; 8 2-0-0 1
17│ bne.s @b ; 10 6-0-0 0
18│ ; =22 =10 =10
19│ rts
20│
21│_op_name::
22│ .dc.b 'nop',0
●結果
・X68000XVI 10MHz での結果
[nop] total=11313(μs) count=5000 each=2.2626(μs) each=22.626(clock/10MHz)
・X68000XVI 16MHz での結果
[nop] total=10694(μs) count=8000 each=1.3368(μs) each=22.2796(clock/16.667MHz)
・X68000XVI 24MHz(REDZONE)での結果
[nop] total=9191(μs) count=10000 each=0.9191(μs) each=22.0584(clock/24MHz)
・X68030 での結果
[nop] total=8000(μs) count=20000 each=0.4(μs) each=10(clock/25MHz)
・X68030+060turbo での結果
[nop] total=10000(μs) count=50000 each=0.2(μs) each=10(clock/50MHz)
●補足
68060 のクロック数が多いのは、NOP 命令がパイプラインを掃除するための命
令だからです。コードにパッチを当てるときに隙間を埋めるためには
MOVEA.L A0,A0 を使います。
━───────────────────────────────────
具体例(その2)
────────────────────────────────────
MULU.W Dn,Dn+SUBQ.L #xx,Dn+Bcc.S の所要クロック数を調べます。
MULU.W Dn,Dn は 68000 では 38~70 クロック、68030 では 28 クロック、
68060 では 2 クロックの命令です。これを確認します。68000 のクロック数は
ソースオペランドに含まれる 1 のビットの数に比例しますが、ここではワース
トケースの $FFFF で計っています。
MULU.W Dn,Dn 1 回の所要時間が X68000XVI 10MHz で 7μs、060turbo で
0.04μs ですから、ワーストケースで所要時間が 175 倍も違うことがわかりま
す。
●ソース
┌────────────────────────────────
1│;mulu+subq.l+bcc.s
2│ .text
3│ .even
4│_op_init::
5│ move.l (4,sp),d0
6│ move.w #$FFFF,d1 ;worst case
7│ rts
8│
9│ .even
10│_op_tini::
11│ rts
12│
13│ .align 16
14│_op_main::
15│ ; 000 030 060
16│@@: move.w d1,d2 ; 4 2-0-0 1
17│ mulu.w d2,d2 ; 70 2-26-0 2
18│ subq.l #1,d0 ; 8 2-0-0 1
19│ bne.s @b ; 10 6-0-0 0
20│ ; =92 =38 =4
21│ rts
22│
23│_op_name::
24│ .dc.b 'mulu',0
●結果
・X68000XVI 10MHz での結果
[mulu] total=9245(μs) count=1000 each=9.245(μs) each=92.45(clock/10MHz)
・X68000XVI 16MHz での結果
[mulu] total=11063(μs) count=2000 each=5.5315(μs) each=92.1935(clock/16.667MHz)
・X68000XVI 24MHz(REDZONE)での結果
[mulu] total=11529(μs) count=3000 each=3.843(μs) each=92.232(clock/24MHz)
・X68030 での結果
[mulu] total=12161(μs) count=8000 each=1.5201(μs) each=38.0031(clock/25MHz)
・X68030+060turbo での結果
[mulu] total=12000(μs) count=150000 each=0.08(μs) each=4(clock/50MHz)
(EOF)